home *** CD-ROM | disk | FTP | other *** search
/ Hot Super Models / Hot Super Models.iso / unix / x11 / xv200.tar / xv-2.00 / unsupt / vicar < prev    next >
Text File  |  1992-01-01  |  78KB  |  2,148 lines

  1. (Message /usr/users/bradley/Mail/inbox:27)
  2. Return-Path: datri@lovecraft.convex.com
  3. Received-Date: Tue, 29 Oct 91 15:06:28 EST
  4. Received: from convex.convex.com by central.cis.upenn.edu
  5.     id AA26939; Tue, 29 Oct 91 15:06:07 -0500
  6. Posted-Date: Tue, 29 Oct 1991 14:03:52 -0600 (CST)
  7. Received: from lovecraft.convex.com by convex.convex.com (5.61/1.35)
  8.     id AA23755; Tue, 29 Oct 91 14:03:55 -0600
  9. Received: by lovecraft.convex.com (4.1/SMI-4.1)
  10.     id AA26110; Tue, 29 Oct 91 14:03:53 CST
  11. Received: from Messages.7.15.N.CUILIB.3.45.SNAP.NOT.LINKED.lovecraft.convex.com.sun4.41
  12.           via MS.5.6.lovecraft.convex.com.sun4_41;
  13.           Tue, 29 Oct 1991 14:03:52 -0600 (CST)
  14. Message-Id: <wd3Pucm2e4NhRWUuI=@concave>
  15. Date: Tue, 29 Oct 1991 14:03:52 -0600 (CST)
  16. From: "Anthony A. Datri" <datri@concave.convex.com>
  17. To: bradley@central.cis.upenn.edu
  18. Subject: xv
  19.  
  20. I hear that you're intested in my additions to xv after all.  There's a
  21. tar file of the whole thing on convex.com for anonymous ftp, and here
  22. are the diffs that I think should work.
  23.  
  24. Add a line to the Makefile like
  25.  
  26. # if you don't have strstr, uncomment this
  27. STRSTRF = #-DNOSTRSTR
  28.  
  29.  
  30.  
  31. # This is a shell archive.  Remove anything before this line,
  32. # then unpack it by saving it in a file and typing "sh file".
  33. #
  34. # Wrapped by lovecraft!datri on Tue Oct 29 13:59:32 CST 1991
  35. # Contents:  diff pds.h pdsuncomp.c xvpds.c
  36.  
  37. echo x - diff
  38. sed 's/^@//' > "diff" <<'@//E*O*F diff//'
  39. diff -c pristine/xv.c xv/xv.c
  40. *** pristine/xv.c    Thu Nov 29 12:44:53 1990
  41. --- xv/xv.c    Tue Sep  3 13:50:45 1991
  42. ***************
  43. *** 53,58 ****
  44. --- 53,59 ----
  45.   #define PM      2
  46.   #define PBM     3
  47.   #define XBM     4
  48. + #define PDS    5
  49.   
  50.   static unsigned long rootbg, rootfg;  /* fg/bg for root border */
  51.   static int    waitsec = -1;     /* seconds between pics. -1=wait for event */
  52. ***************
  53. *** 785,791 ****
  54.     else if (magicno[0] == 'P' && magicno[1]>='1' && 
  55.          magicno[1]<='6') filetype = PBM;
  56.   
  57. !   else if (strncmp(magicno,"#define",7)==0) filetype = XBM;
  58.   
  59.     if (filetype == UNKNOWN) {
  60.       SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basename);
  61. --- 786,798 ----
  62.     else if (magicno[0] == 'P' && magicno[1]>='1' && 
  63.          magicno[1]<='6') filetype = PBM;
  64.   
  65. !  /* this doesn't *really* detect the full magic, since the above
  66. !     code only reads 8 bytes */
  67. !   else if (strncmp(magicno,"NJPL1I00",8)==0 ||
  68. !        strncmp(magicno+2,"NJPL1I",6)==0 ||
  69. !        strncmp(magicno,"LBLSIZE=",8)==0) {
  70. !     filetype = PDS;
  71. !   }  else if (strncmp(magicno,"#define",7)==0) filetype = XBM;
  72.   
  73.     if (filetype == UNKNOWN) {
  74.       SetISTR(ISTR_INFO,"'%s' not in a recognized format.", basename);
  75. ***************
  76. *** 800,805 ****
  77. --- 807,813 ----
  78.     case PM:  i = LoadPM (filename,ncols); break;
  79.     case PBM: i = LoadPBM(filename,ncols); break;
  80.     case XBM: i = LoadXBM(filename,ncols); break;
  81. +   case PDS: i = LoadPDS(filename,ncols); break;
  82.     }
  83.     WaitCursor();
  84.   
  85. diff -c pristine/xv.h xv/xv.h
  86. *** pristine/xv.h    Thu Nov 29 12:45:35 1990
  87. --- xv/xv.h    Fri Sep  6 10:37:04 1991
  88. ***************
  89. *** 38,45 ****
  90.   #endif
  91.   
  92.   /* neither IBM AOS 4.3, Convex, nor BSD 4.3 on VAX have <malloc.h> */
  93. ! #if !defined(ibm032) && !defined(__convexc__) && \
  94. !     !(defined(vax) && !defined(ultrix))
  95.   #if defined(hp300) || defined(hp800)
  96.   #include <sys/malloc.h>                /* it's in 'sys' on HPs*/
  97.   #else
  98. --- 38,44 ----
  99.   #endif
  100.   
  101.   /* neither IBM AOS 4.3, Convex, nor BSD 4.3 on VAX have <malloc.h> */
  102. ! #if !defined(ibm032) && !defined(__convexc__) && !(defined(vax) &&
  103. !defined(ultrix))
  104.   #if defined(hp300) || defined(hp800)
  105.   #include <sys/malloc.h>                /* it's in 'sys' on HPs*/
  106.   #else
  107. ***************
  108. *** 558,567 ****
  109.   int LoadXBM(char *, int);
  110.   int WriteXBM(FILE *, byte *, int, int, char *);
  111.   
  112.   
  113.   #else     /* using non-ANSI cc.  Function defs, but no params */
  114.   
  115.   
  116. --- 557,565 ----
  117.   int LoadXBM(char *, int);
  118.   int WriteXBM(FILE *, byte *, int, int, char *);
  119.   
  120. + /**************************** XVPDS.C ***************************/
  121. + int LoadPDS(char *, int);
  122.   
  123.   #else     /* using non-ANSI cc.  Function defs, but no params */
  124.   
  125.   
  126. ***************
  127. *** 632,636 ****
  128. --- 630,636 ----
  129.   /**************************** XVXBM.C ***************************/
  130.   int LoadXBM(), WriteXBM();
  131.   
  132. + /**************************** XVPDS.C ***************************/
  133. + int LoadPDS();
  134.   
  135.   #endif
  136. @//E*O*F diff//
  137. chmod u=rw,g=r,o=r diff
  138.  
  139. echo x - pds.h
  140. sed 's/^@//' > "pds.h" <<'@//E*O*F pds.h//'
  141. #define PDSFIXED    (1)
  142. #define    PDSVARIABLE    (2)
  143. #define PDSTRASH    (-1)
  144. #define VICAR        (3)
  145.  
  146. @//E*O*F pds.h//
  147. chmod u=rw,g=r,o=r pds.h
  148.  
  149. echo x - pdsuncomp.c
  150. sed 's/^@//' > "pdsuncomp.c" <<'@//E*O*F pdsuncomp.c//'
  151. /* datri@convex.com, 4-14-91
  152.    This file is taken almost unchanged from the NASA CD-ROMS of the Voyager
  153.    images.  I can find no copyright anywhere near this code.
  154.    All I've done is added - as a special case for the output
  155.    filename to go to stdout, and made informational messages go to stderr
  156.    instead of stdout, removing some of the silly ones.  I've also corrected
  157.    some of the places where fools assume that VAX and VMS are synonymous */
  158.  
  159. /********************************************************************/
  160. /*  Voyager Image Decompression Program - C Version for PC, VAX,    */
  161. /*  UNIX and Macintosh systems.                                     */
  162. /*                                                                  */
  163. /*  Decompresses images using Kris Becker's subroutine DECOMP.C     */
  164. /*  which is included in this program in a shortened version.       */
  165. /*                                                                  */
  166. /*  Reads a variable length compressed VOYAGER image and outputs a  */
  167. /*  fixed length uncompressed image file in PDS format with         */
  168. /*  labels, image histogram, engineering table and 800 lines of     */
  169. /*  836 bytes (800 samples, 36 engineering bytes); or an 800 by     */
  170. /*  800 array with FITS, VICAR or no labels.  If used on a non-     */
  171. /*  byte-swapped machine the image histogram is un-swapped.         */
  172. /*                                                                  */
  173. /********************************************************************/
  174. /*                                                                  */
  175. /*  Use the following commands to compile and link to produce an    */
  176. /*  executable file:                                                */
  177. /*                                                                  */
  178. /*  On an IBM PC (using Microsoft C Version 5.x)                    */
  179. /*                                                                  */
  180. /*    cl /c cdcomp.c                                                */
  181. /*    link  cdcomp/stack:10000;                                     */
  182. /*                                                                  */
  183. /*  On a VAX:                                                       */
  184. /*                                                                  */
  185. /*    cc   cdcomp                                                   */
  186. /*    $define lnk$library sys$library:vaxcrtl.olb                   */
  187. /*    link cdcomp                                                   */
  188. /*                                                                  */
  189. /*  On a Unix host (Sun, Masscomp)                                  */
  190. /*                                                                  */
  191. /*    cc -o cdcomp cdcomp.c                                         */
  192. /*                                                                  */
  193. /*  On a Macintosh (using Lightspeed C)                             */
  194. /*                                                                  */
  195. /*    link with the following libraries:                            */
  196. /*    stdio, storage, strings, unix and MacTraps, with MacTraps     */
  197. /*    in a separate segment.                                        */
  198. /*                                                                  */
  199. /********************************************************************/
  200. /*                                                                  */
  201. /*  Use the following command to run the program:                   */
  202. /*                                                                  */
  203. /*    CDCOMP [infile] [outfile] [output format]                     */
  204. /*                                                                  */
  205. /*       infile        - name of compressed image file.             */
  206. /*       outfile       - name of uncompressed output file.          */
  207. /*       output format - selected from the following list:          */
  208. /*                                                                  */
  209. /*          1  SFDU/PDS format [DEFAULT].                           */
  210. /*          2  FITS format.                                         */
  211. /*          3  VICAR format.                                        */
  212. /*          4  Unlabelled binary array.                             */
  213. /*                                                                  */
  214. /*  Under VMS you will need to 'install' the program to            */
  215. /*  be able to use command line arguments using the following       */
  216. /*  command:                                                        */
  217. /*                                                                  */
  218. /*  $ vaxdcomp :== $DISKNAME:[DIRECTORY]vaxcomp.exe                 */
  219. /*                                                                  */
  220. /*  where DISKNAME is the disk drive and DIRECTORY is the           */
  221. /*  directory where VAXDCOMP.EXE is stored.                         */
  222. /*                                                                  */
  223. /********************************************************************/
  224. /*                                                                  */
  225. /* LIMS                                                             */
  226. /*  This program has been tested on a VAX 780 (VMS 4.6), SUN        */
  227. /*  Workstation (UNIX 4.2, release 3.4), an IBM PC                  */
  228. /*  (MICROSOFT 5.1 compiler) and Macintosh IIx using Lightspeed C   */
  229. /*  version 3.0.  When converting to other systems, check for       */
  230. /*  portability conflicts.                                          */
  231. /*                                                                  */
  232. /* HIST                                                             */
  233. /*  AUG89 Added code to get command line arguments for filenames    */
  234. /*  and output format; routines to free memory used by the Huffman  */
  235. /*  tree); fixed the SFDU label output length; and modified the     */
  236. /*  I/O routines so that the open for Host type 2 uses binary I/O.  */
  237. /*  JUN89 Fixed READVAR, to get length on 16-bit unswapped hosts.   */
  238. /*  JUL88 C driver to decompress standard Voyager Compressed images */
  239. /*  by Mike Martin 1989/06/10                                       */
  240. /*                                                                  */
  241. /*  Inputs   - Input file to be decompressed.                       */
  242. /*                                                                  */
  243. /*  Outputs  - Output file containing decompressed image.           */
  244. /*                                                                  */
  245. /********************************************************************/
  246.  
  247. #include <stdio.h>
  248.  
  249. #define TRUE                  1
  250. #define FALSE                 0
  251. #define RECORD_BYTES        836
  252.  
  253.                                     /* pc i/o defines               */
  254. #define O_RDONLY         0x0000     /* open for reading only        */
  255. #define O_BINARY         0x8000     /* file mode is binary          */
  256.  
  257.                                     /* vax i/o defines              */
  258. #define RECORD_TYPE      "rfm=fix"  /* VMS fixed length output      */
  259. #define CTX              "ctx=bin"  /* no translation of \n         */
  260. #define FOP          "fop=cif,sup"  /* file processing ops          */
  261.  
  262. typedef struct leaf
  263.   {
  264.    struct leaf *right;
  265.    short int dn;
  266.    struct leaf *left;
  267.   } NODE;
  268.  
  269. /*************************************************************************
  270.  Declare the tree pointer. This pointer will hold the root of the tree
  271.  once the tree is created by the accompanying routine huff_tree.
  272. **************************************************************************/
  273.  
  274.   NODE *tree;
  275.  
  276. /* subroutine definitions                                           */
  277.  
  278. void               pds_labels();
  279. void               fits_labels();
  280. void               vicar_labels();
  281. void               no_labels();
  282. int                check_host();
  283. int                get_files();
  284. long               swap_long();
  285. void               decompress();
  286. void               decmpinit();
  287. void               free_tree();
  288.  
  289. /* global variables                                                 */
  290.  
  291. int                infile,Argc;
  292. FILE               *outfile;
  293. char               inname[80],outname[80];
  294. int                output_format;
  295.  
  296. main(argc,argv)
  297.  
  298. int  argc;
  299. char **argv;
  300.  
  301. {
  302. char          ibuf[2048],obuf[2048];
  303. unsigned char blank=32;
  304. short         host,length,total_bytes,line,i;
  305. long          long_length,hist[511];
  306. int           out_bytes = RECORD_BYTES;
  307. int           count;
  308.  
  309. /*********************************************************************/
  310. /*                                                                   */
  311. /* get host information and input and output files                   */
  312. /*                                                                   */
  313. /*********************************************************************/
  314.  
  315.    Argc=argc;
  316.    strcpy(inname,"   ");
  317.    strcpy(outname,"   ");
  318.    output_format = 0;
  319.  
  320.    if (argc == 1);                     /* prompt user for parameters */
  321.    else if (argc == 2 && (strncmp(argv[1],"help",4) == 0 || 
  322.                           strncmp(argv[1],"HELP",4) == 0 ||
  323.                           strncmp(argv[1],"?",1)    == 0))
  324.      {
  325.       fprintf(stderr,"Voyager Image Decompression Program.  Command line
  326. format:\n\n");
  327.       fprintf(stderr,"CDCOMP [infile] [outfile] [format code]\n");
  328.       fprintf(stderr,"   infile        - name of compressed image file. 
  329.    \n");
  330.       fprintf(stderr,"   outfile       - name of uncompressed output
  331. file.  \n");
  332.       fprintf(stderr,"   output format - selected from the following
  333. list:  \n");   
  334.       fprintf(stderr,"                                                  
  335.    \n");   
  336.       fprintf(stderr,"     1  SFDU/PDS format [DEFAULT].                
  337.    \n");   
  338.       fprintf(stderr,"     2  FITS format.                              
  339.    \n");   
  340.       fprintf(stderr,"     3  VICAR format.                             
  341.    \n");   
  342.       fprintf(stderr,"     4  Unlabelled binary array.                  
  343.  \n\n");   
  344.       exit(1);
  345.      }  
  346.    else 
  347.      {
  348.       strcpy(inname,argv[1]);  
  349.       if (argc >= 3) strcpy(outname,argv[2]); 
  350.       if (argc == 3) output_format = 1;
  351.       if (argc == 4) sscanf(argv[3],"%d",&output_format); 
  352.      }
  353.    host = check_host();
  354.    host = get_files(host); /* may change host if VAX */
  355.  
  356. /*********************************************************************/
  357. /*                                                                   */
  358. /* read and edit compressed file labels                              */
  359. /*                                                                   */
  360. /*********************************************************************/
  361.  
  362.    switch (output_format)
  363.      {
  364.        case 1: pds_labels(host);
  365.                break;
  366.        case 2: fits_labels(host);
  367.                break;
  368.        case 3: vicar_labels(host);
  369.                break;
  370.        case 4: no_labels(host);
  371.      }
  372. /*********************************************************************/
  373. /*                                                                   */
  374. /* process the image histogram                                       */
  375. /*                                                                   */
  376. /*********************************************************************/
  377.  
  378. /* need to know record_bytes,hist_count,hist_item_type,item_count.*/
  379.    total_bytes = 0;
  380.    length = read_var((char *)hist,host);
  381.    total_bytes = total_bytes + length;
  382.    length = read_var((char *)hist+836,host);
  383.    total_bytes = total_bytes + length;
  384.  
  385.    if (host == 2 || host == 5)             /* If non-byte swapped    */
  386.      for (i=0;i<256;i++)                   /* host, swap bytes in    */
  387.        hist[i] = swap_long(hist[i]);       /* the output histogram   */
  388.  
  389.    if (output_format == 1)
  390.      {
  391.       fwrite((char *)hist,    836,1,outfile);
  392.       fwrite((char *)hist+836,length,1,outfile);
  393.  
  394.       /*  pad out the histogram to a multiple of RECORD_BYTES */
  395.       for (i=total_bytes;i<RECORD_BYTES*2;i++) fputc(blank,outfile);
  396.      }
  397. /*********************************************************************/
  398. /*                                                                   */
  399. /* process the encoding histogram                                    */
  400. /* don't have to byte-swap because DECOMP.C does it for us           */
  401. /*                                                                   */
  402. /*********************************************************************/
  403.  
  404.    length = read_var((char *)hist,host);
  405.    length = read_var((char *)hist+836,host);
  406.    length = read_var((char *)hist+1672,host);
  407.  
  408. /*********************************************************************/
  409. /*                                                                   */
  410. /* process the engineering summary                                   */
  411. /*                                                                   */
  412. /*********************************************************************/
  413.  
  414.    total_bytes = 0;
  415.    length = read_var(ibuf,host);
  416.  
  417.    if (output_format == 1)
  418.      {
  419.       fwrite(ibuf,length,1,outfile);
  420.       total_bytes = total_bytes + length;
  421.  
  422.       /*  pad out engineering to multiple of 836 */
  423.       for (i=total_bytes;i<RECORD_BYTES;i++) fputc(blank,outfile);
  424.      }
  425. /*********************************************************************/
  426. /*                                                                   */
  427. /* initialize the decompression                                      */
  428. /*                                                                   */
  429. /*********************************************************************/
  430.  
  431. /*stupid    fprintf(stderr,"\nInitializing decompression routine..."); */
  432.     decmpinit(hist);
  433.  
  434. /*********************************************************************/
  435. /*                                                                   */
  436. /* decompress the image                                              */
  437. /*                                                                   */
  438. /*********************************************************************/
  439.  
  440. /* stupid
  441.     printf("\nDecompressing data..."); */
  442.     line=0;
  443.     do
  444.       {
  445.        length = read_var(ibuf,host);
  446.        if (length <= 0) break;
  447.        long_length = (long)length;
  448.        line += 1;
  449.        decompress(ibuf, obuf,&long_length, &out_bytes);
  450.        if (output_format == 1)
  451.          {
  452.           count = fwrite(obuf,RECORD_BYTES,1,outfile);
  453.           if (count != 1)
  454.             {
  455.              fprintf(stderr,"\nError writing output file.  Aborting program.");
  456.              fprintf(stderr,"\nCheck disk space or for duplicate file
  457. name (VMS).");
  458.              exit(1);
  459.             }
  460.          }
  461.        else fwrite(obuf,800,1,outfile);
  462.  
  463. /* stupid        if (line % 100 == 0) printf("\n line %d",line);*/
  464.       } while (length > 0 && line < 800);
  465.  
  466.  /*  pad out FITS file to a multiple of 2880 */
  467.  if (output_format == 2)
  468.    for (i=0;i<2240;i++) fputc(blank,outfile);
  469.  
  470. /*stupid printf("\n");*/
  471.  free_tree(&long_length);
  472.  close(infile);
  473.  fclose(outfile);
  474. }
  475.  
  476. /*********************************************************************/
  477. /*                                                                   */
  478. /* subroutine get_files - get input filenames and open               */
  479. /*                                                                   */
  480. /*********************************************************************/
  481.  
  482. int get_files(host)
  483. int host;
  484.  
  485. {
  486. short   shortint;
  487.  
  488.   if (inname[0] == ' ')
  489.     {
  490.      fprintf(stderr,"\nEnter name of file to be decompressed: ");
  491.      gets (inname);
  492.     }
  493.   if (host == 1 | host == 2)
  494.     {
  495.      if ((infile = open(inname,O_RDONLY | O_BINARY)) <= 0)
  496.        {
  497.         fprintf(stderr,"\ncan't open input file: %s\n",inname);
  498.         exit(1);
  499.        }
  500.     }
  501.   else if (host == 3 | host == 5)
  502.     {
  503.      if ((infile = open(inname,O_RDONLY)) <= 0)
  504.        {
  505.         fprintf(stderr,"\ncan't open input file: %s\n",inname);
  506.         exit(1);
  507.        }
  508.  
  509.   /****************************************************************/
  510.   /* If we are on a vax see if the file is in var length format.  */
  511.   /* This logic is in here in case the vax file has been stored   */
  512.   /* in fixed or undefined format.  This might be necessary since */
  513.   /* vax variable length files can't be moved to other computer   */
  514.   /* systems with standard comm programs (kermit, for example).   */
  515.   /****************************************************************/
  516.  
  517.      if (host == 3)
  518.        {
  519.         read(infile,&shortint,2);
  520.         if (shortint > 0 && shortint < 80)
  521.           {
  522.            host = 4;              /* change host to 4                */
  523.            fprintf(stderr,"This is not a VMS variable length file.");
  524.           }
  525.         else fprintf(stderr,"This is a VMS variable length file.");
  526.         lseek(infile,0,0);        /* reposition to beginning of file */
  527.        }
  528.     }
  529.  
  530.   if (output_format == 0)
  531.   do
  532.     {
  533.      fprintf(stderr,"\nEnter a number for the output format desired:\n");
  534.      fprintf(stderr,"\n  1.  SFDU/PDS format.");
  535.      fprintf(stderr,"\n  2.  FITS format.");
  536.      fprintf(stderr,"\n  3.  VICAR format.");
  537.      fprintf(stderr,"\n  4.  Unlabelled binary array.\n");
  538.      fprintf(stderr,"\n  Enter format number:");
  539.      gets(inname);
  540.      output_format = atoi(inname);
  541.     } while (output_format < 1 || output_format > 4);
  542.  
  543.   if (outname[0] == ' ')
  544.     {
  545.      fprintf(stderr,"\nEnter name of uncompressed output file: ");
  546.      gets (outname);
  547.     }
  548.  
  549.   if (*outname == '-') {    /* write to stdout */
  550.     outfile = stdout;
  551.     return(host);
  552.   }
  553.   if (host == 1 || host == 2 || host == 5)
  554.     {
  555.      if ((outfile = fopen(outname,"wb"))==NULL)
  556.        {
  557.         fprintf(stderr,"\ncan't open output file: %s\n",outname);
  558.         exit(1);
  559.        }
  560.     }
  561. /* ANSI C doesn't like the extra crappy arguments to fopen below */
  562. #ifndef __unix__
  563.   else if (host == 3 || host == 4)
  564.     {
  565.      if (output_format == 1)      /* write PDS format blocks */
  566.        {
  567.         if ((outfile=fopen(outname,"w",
  568.                            "mrs=836",FOP,CTX,RECORD_TYPE))==NULL)
  569.          {
  570.           fprintf(stderr,"\ncan't open output file: %s\n",outname);
  571.           exit(1);
  572.          }
  573.        }
  574.      else if (output_format == 2) /* write FITS format blocks */
  575.        {
  576.         if ((outfile=fopen(outname,"w",
  577.                            "mrs=2880",FOP,CTX,RECORD_TYPE))==NULL)
  578.          {
  579.           fprintf(stderr,"\ncan't open output file: %s\n",outname);
  580.           exit(1);
  581.          }
  582.        }
  583.      else                         /* write 800 byte records */
  584.        {
  585.         if ((outfile=fopen(outname,"w",
  586.                            "mrs=800",FOP,CTX,RECORD_TYPE))==NULL)
  587.          {
  588.           fprintf(stderr,"\ncan't open output file: %s\n",outname);
  589.           exit(1);
  590.          }
  591.        }
  592.     }
  593. #endif
  594.   return(host);  /* In case its been updated */
  595. }
  596.  
  597. /*********************************************************************/
  598. /*                                                                   */
  599. /* subroutine pds_labels - edit PDS labels and write to output file  */
  600. /*                                                                   */
  601. /*********************************************************************/
  602.  
  603. void pds_labels(host)
  604. int host;
  605.  
  606. {
  607. char          outstring[80],ibuf[2048];
  608. unsigned char cr=13,lf=10,blank=32;
  609. short         length,nlen,total_bytes,line,i;
  610.  
  611.  
  612. total_bytes = 0;
  613. do
  614.   {
  615.    length = read_var(ibuf,host);
  616.    ibuf[length]=NULL;
  617.  
  618.   /******************************************************************/
  619.   /*  edit labels which need to be changed                          */
  620.   /******************************************************************/
  621.  
  622.    if      ((i = strncmp(ibuf,"NJPL1I00PDS1",12)) == 0)
  623.    /*****************************************************************/
  624.    /* add the output file length to the sfdu label                  */
  625.    /*****************************************************************/
  626.      {
  627.       strcpy(outstring,ibuf);
  628.       strcpy(outstring+12,"00673796");
  629.       strcpy(outstring+20,ibuf+20);
  630.       fwrite(outstring,length,1,outfile);
  631.       fprintf(outfile,"%c%c",cr,lf);
  632.       total_bytes = total_bytes + length + 2;
  633.      }
  634.    else if ((i = strncmp(ibuf,"RECORD_TYPE",11)) == 0)
  635.    /*****************************************************************/
  636.    /* change the record_type value from variable to fixed           */
  637.    /*****************************************************************/
  638.      {
  639.       strcpy(ibuf+35,"FIXED_LENGTH");
  640.       length = length - 3;
  641.       fwrite(ibuf,length,1,outfile);
  642.       fprintf(outfile,"%c%c",cr,lf);
  643.       total_bytes = total_bytes + length + 2;
  644.      }
  645.    else if ((i = strncmp(ibuf,"FILE_RECORDS",12)) == 0)
  646.    /*****************************************************************/
  647.    /* change the file_records count to 806                          */
  648.    /*****************************************************************/
  649.      {
  650.       strcpy(ibuf+35,"806");
  651.       fwrite(ibuf,length,1,outfile);
  652.       fprintf(outfile,"%c%c",cr,lf);
  653.       total_bytes = total_bytes + length + 2;
  654.      }
  655.    else if ((i = strncmp(ibuf,"LABEL_RECORDS",13)) == 0)
  656.    /*****************************************************************/
  657.   /* change the label_records count from 56 to 3                    */
  658.    /*****************************************************************/
  659.      {
  660.       strcpy(ibuf+35,"3");
  661.       length -= 1;
  662.       fwrite(ibuf,length,1,outfile);
  663.       fprintf(outfile,"%c%c",cr,lf);
  664.       total_bytes = total_bytes + length + 2;
  665.      }
  666.    else if ((i = strncmp(ibuf,"^IMAGE_HISTOGRAM",16)) == 0)
  667.    /*****************************************************************/
  668.    /* change the location pointer of image_histogram to record 4    */
  669.    /*****************************************************************/
  670.      {
  671.       strcpy(ibuf+35,"4");
  672.       length -= 1;
  673.       fwrite(ibuf,length,1,outfile);
  674.       fprintf(outfile,"%c%c",cr,lf);
  675.       total_bytes = total_bytes + length + 2;
  676.      }
  677.    else if ((i = strncmp(ibuf,"^ENCODING_HISTOGRAM)",19)) == 0);
  678.    /*****************************************************************/
  679.    /* delete the encoding_histogram location pointer                */
  680.    /*****************************************************************/
  681.    else if ((i = strncmp(ibuf,"^ENGINEERING_TABLE",18)) == 0)
  682.    /*****************************************************************/
  683.    /* change the location pointer of engineering_summary to record 6*/
  684.    /*****************************************************************/
  685.      {
  686.       strcpy(ibuf+35,"6");
  687.       length -= 1;
  688.       fwrite(ibuf,length,1,outfile);
  689.       fprintf(outfile,"%c%c",cr,lf);
  690.       total_bytes = total_bytes + length + 2;
  691.      }
  692.    else if ((i = strncmp(ibuf,"^IMAGE",6)) == 0)
  693.    /*****************************************************************/
  694.    /* change the location pointer of image to record 7              */
  695.    /*****************************************************************/
  696.      {
  697.       strcpy(ibuf+35,"7");
  698.       length = length -1;
  699.       fwrite(ibuf,length,1,outfile);
  700.       fprintf(outfile,"%c%c",cr,lf);
  701.       total_bytes = total_bytes + length + 2;
  702.      }
  703.    else if ((i = strncmp(ibuf,
  704.              "OBJECT                           = ENCODING",43)) == 0)
  705.    /*****************************************************************/
  706.    /* delete the 4 encoding histogram labels                        */
  707.    /*****************************************************************/
  708.      {
  709.       for (i=0;i<4;i++)   /* ignore these labels */
  710.         {
  711.          length = read_var(ibuf,host);
  712.         }
  713.      }
  714.    else if ((i = strncmp(ibuf," ENCODING",9)) == 0);
  715.    /*****************************************************************/
  716.    /* delete the encoding type label in the image object            */
  717.    /*****************************************************************/
  718.    else if ((host == 2 || host == 5) && (i = strncmp(ibuf,
  719.              " ITEM_TYPE                       = VAX_INTEGER",46)) == 0)
  720.    /*****************************************************************/
  721.    /* change the record_type value from variable to fixed           */
  722.    /*****************************************************************/
  723.      {
  724.       strcpy(ibuf+35,"INTEGER");
  725.       length = length - 4;
  726.       fwrite(ibuf,length,1,outfile);
  727.       fprintf(outfile,"%c%c",cr,lf);
  728.       total_bytes = total_bytes + length + 2;
  729.      }
  730.  
  731.  
  732.  
  733.    /*****************************************************************/
  734.    /* if none of above write out the label to the output file       */
  735.    /*****************************************************************/
  736.    else
  737.      {
  738.       fwrite(ibuf,length,1,outfile);
  739.       fprintf(outfile,"%c%c",cr,lf);
  740.       total_bytes = total_bytes + length + 2;
  741.      }
  742.    /*****************************************************************/
  743.    /* test for the end of the PDS labels                            */
  744.    /*****************************************************************/
  745.    if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
  746.   } while (length > 0);
  747.  
  748. /* pad out the labels with blanks to multiple of RECORD_BYTES */
  749.    for (i=total_bytes;i<RECORD_BYTES*3;i++) fputc(blank,outfile);
  750. }
  751.  
  752. /*********************************************************************/
  753. /*                                                                   */
  754. /* subroutine fits_labels - write FITS header to output file */
  755. /*                                                                   */
  756. /*********************************************************************/
  757.  
  758. void fits_labels(host)
  759. int host;
  760.  
  761. {
  762. char          ibuf[2048],outstring[80];
  763. unsigned char cr=13,lf=10,blank=32;
  764. short         length,nlen,total_bytes,line,i;
  765.  
  766. do
  767.   {
  768.    length = read_var(ibuf,host);
  769.    /*****************************************************************/
  770.    /* read to the end of the PDS labels                             */
  771.    /*****************************************************************/
  772.    if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
  773.   } while (length > 0);
  774.  
  775. total_bytes = 0;
  776.  
  777. strcpy(outstring,
  778. "SIMPLE  =                    T                                         
  779.       ");
  780. fwrite(outstring,78,1,outfile);
  781. fprintf(outfile,"%c%c",cr,lf);
  782. total_bytes = total_bytes + 80;
  783.  
  784. strcpy(outstring,
  785. "BITPIX  =                    8                                         
  786.       ");
  787. fwrite(outstring,78,1,outfile);
  788. fprintf(outfile,"%c%c",cr,lf);
  789. total_bytes = total_bytes + 80;
  790.  
  791. strcpy(outstring,
  792. "NAXIS   =                    2                                         
  793.       ");
  794. fwrite(outstring,78,1,outfile);
  795. fprintf(outfile,"%c%c",cr,lf);
  796. total_bytes = total_bytes + 80;
  797.  
  798. strcpy(outstring,
  799. "NAXIS1  =                  800                                         
  800.       ");
  801. fwrite(outstring,78,1,outfile);
  802. fprintf(outfile,"%c%c",cr,lf);
  803. total_bytes = total_bytes + 80;
  804.  
  805. strcpy(outstring,
  806. "NAXIS2  =                  800                                         
  807.       ");
  808. fwrite(outstring,78,1,outfile);
  809. fprintf(outfile,"%c%c",cr,lf);
  810. total_bytes = total_bytes + 80;
  811.  
  812. strcpy(outstring,
  813. "END                                                                    
  814.       ");
  815. fwrite(outstring,78,1,outfile);
  816. fprintf(outfile,"%c%c",cr,lf);
  817. total_bytes = total_bytes + 80;
  818.  
  819. /* pad out the labels with blanks to multiple of RECORD_BYTES */
  820.    for (i=total_bytes;i<2880;i++) fputc(blank,outfile);
  821. }
  822.  
  823. /*********************************************************************/
  824. /*                                                                   */
  825. /* subroutine vicar_labels - write vicar labels to output file       */
  826. /*   (really, really shouldn't assume 800x800                 */
  827. /*********************************************************************/
  828.  
  829. void vicar_labels(host)
  830. int host;
  831.  
  832. {
  833. char          ibuf[2048],outstring[80];
  834. unsigned char cr=13,lf=10,blank=32;
  835. short         length,nlen,total_bytes,line,i;
  836.  
  837. do
  838.   {
  839.    length = read_var(ibuf,host);
  840.    /*****************************************************************/
  841.    /* read to the end of the PDS labels                             */
  842.    /*****************************************************************/
  843.    if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
  844.   } while (length > 0);
  845.  
  846. total_bytes = 0;
  847.  
  848. strcpy(outstring,
  849. "LBLSIZE=800             FORMAT='BYTE'  TYPE='IMAGE'  BUFSIZ=800  DIM=2  ");
  850. fwrite(outstring,72,1,outfile);
  851. total_bytes = total_bytes + 72;
  852. strcpy(outstring,
  853. "EOL=0  RECSIZE=800  ORG='BSQ'  NL=800  NS=800  NB=1  N1=0  N2=0  N3=0  ");
  854. total_bytes = total_bytes + 71;
  855. fwrite(outstring,71,1,outfile);
  856. strcpy(outstring,
  857. "N4=0  NBB=0  NLB=0");
  858. fwrite(outstring,18,1,outfile);
  859. fprintf(outfile,"%c%c",cr,lf);
  860. total_bytes = total_bytes + 20;
  861.  
  862. /* pad out the labels with blanks to multiple of RECORD_BYTES */
  863.    for (i=total_bytes;i<800;i++) fputc(blank,outfile);
  864. }
  865.  
  866. /*********************************************************************/
  867. /*                                                                   */
  868. /* subroutine no_labels - read past the pds labels                   */
  869. /*                                                                   */
  870. /*********************************************************************/
  871.  
  872. void no_labels(host)
  873. int host;
  874.  
  875. {
  876. char          ibuf[2048],outstring[80];
  877. unsigned char cr=13,lf=10,blank=32;
  878. short         length,nlen,total_bytes,line,i;
  879.  
  880. do
  881.   {
  882.    length = read_var(ibuf,host);
  883.    /*****************************************************************/
  884.    /* read to the end of the PDS labels                             */
  885.    /*****************************************************************/
  886.    if ((i = strncmp(ibuf,"END",3)) == 0 && length == 3) break;
  887.   } while (length > 0);
  888.  
  889. }
  890.  
  891.  
  892. /*********************************************************************/
  893. /*                                                                   */
  894. /* subroutine read_var - read variable length records from input file*/
  895. /*                                                                   */
  896. /*********************************************************************/
  897.  
  898. read_var(ibuf,host)
  899. char  *ibuf;
  900. int   host;
  901. {
  902. int   length,result,nlen;
  903. char  temp;
  904. union /* this union is used to swap 16 and 32 bit integers          */
  905.   {
  906.    char  ichar[4];
  907.    short slen;
  908.    long  llen;
  909.   } onion;
  910.  
  911.   switch (host)
  912.     {
  913.      case 1: /*******************************************************/
  914.              /* IBM PC host                                         */
  915.              /*******************************************************/
  916.        length = 0;
  917.        result = read(infile,&length,2);
  918.        nlen =   read(infile,ibuf,length+(length%2));
  919.        return (length);
  920.        break;
  921.  
  922.      case 2: /*******************************************************/
  923.              /* Macintosh host                                      */
  924.              /*******************************************************/
  925.        length = 0;
  926.        result = read(infile,onion.ichar,2);
  927.        /*     byte swap the length field                            */
  928.        temp   = onion.ichar[0];
  929.        onion.ichar[0]=onion.ichar[1];
  930.        onion.ichar[1]=temp;
  931.        length = onion.slen;       /* left out of earlier versions   */
  932.        /* printf("length=%04x,result=%d\n",length,result);          */
  933.        nlen =   read(infile,ibuf,length+(length%2));
  934.        return (length);
  935.        break;
  936.  
  937.      case 3: /*******************************************************/
  938.              /* VAX host with variable length support               */
  939.              /*******************************************************/
  940.        length = read(infile,ibuf,RECORD_BYTES);
  941.        return (length);
  942.  
  943.      case 4: /*******************************************************/
  944.              /* VAX host, but not a variable length file            */
  945.              /*******************************************************/
  946.        length = 0;
  947.        result = read(infile,&length,2);
  948.        nlen =   read(infile,ibuf,length+(length%2));
  949.  
  950.        /* check to see if we crossed a vax record boundary          */
  951.        while (nlen < length)
  952.          nlen += read(infile,ibuf+nlen,length+(length%2)-nlen);
  953.        return (length);
  954.        break;
  955.  
  956.      case 5: /*******************************************************/
  957.              /* Unix workstation host (non-byte-swapped 32 bit host)*/
  958.              /*******************************************************/
  959.        length = 0;
  960.        result = read(infile,onion.ichar,2);
  961.        /*     byte swap the length field                            */
  962.        temp   = onion.ichar[0];
  963.        onion.ichar[0]=onion.ichar[1];
  964.        onion.ichar[1]=temp;
  965.        length = onion.slen;
  966.        /* printf("length=%04x,result=%d\n",length,result); */
  967.        nlen =   read(infile,ibuf,length+(length%2));
  968.        return (length);
  969.        break;
  970.     }
  971. }
  972.  
  973. /*********************************************************************/
  974. /*                                                                   */
  975. /* subroutine check_host - find out what kind of machine we are on   */
  976. /*                                                                   */
  977. /*********************************************************************/
  978.  
  979. int check_host()
  980. {
  981. /*  This subroutine checks the attributes of the host computer and
  982.     returns a host code number.
  983. */
  984. char hostname[80];
  985.  
  986. int swap,host,bits,var;
  987. union
  988.   {
  989.    char  ichar[2];
  990.    short ilen;
  991.   } onion;
  992.  
  993. if (sizeof(var) == 4) bits = 32;
  994.                  else bits = 16;
  995.  
  996. onion.ichar[0] = 1;
  997. onion.ichar[1] = 0;
  998.  
  999. if (onion.ilen == 1) swap = TRUE;
  1000. else                 swap = FALSE;
  1001.  
  1002. if (bits == 16 && swap == TRUE)
  1003.   {
  1004.    host = 1; /* IBM PC host  */
  1005.    strcpy(hostname,
  1006.           "Host 1 - 16 bit integers with swapping, no var len support.");
  1007.   }
  1008.  
  1009. if (bits == 16 && swap == FALSE)
  1010.   {
  1011.    host = 2; /* Non byte swapped 16 bit host  */
  1012.    strcpy(hostname,
  1013.           "Host 2 - 16 bit integers without swapping, no var len support.");
  1014.   }
  1015.  
  1016. if (bits == 32 && swap == TRUE)
  1017.  { host = 3; /* VAX host with var length support */
  1018.    strcpy(hostname,
  1019.           "Host 3,4 - 32 bit integers with swapping.");
  1020.  }
  1021.  
  1022. if (bits == 32 && swap == FALSE)
  1023.   {
  1024.    host = 5; /* OTHER 32-bit host  */
  1025.    strcpy(hostname,
  1026.           "Host 5 - 32 bit integers without swapping, no var len support.");
  1027.   }
  1028.  
  1029. if ((Argc >= 3) && (*outname != '-')) /* suppress if stdout (-) on cmdline */
  1030.     fprintf(stderr,"%s\n",hostname);
  1031. return(host);
  1032. }
  1033.  
  1034. long swap_long(inval)  /* swap 4 byte integer                       */
  1035. long inval;
  1036. {
  1037. union /* this union is used to swap 16 and 32 bit integers          */
  1038.   {
  1039.    char  ichar[4];
  1040.    short slen;
  1041.    long  llen;
  1042.   } onion;
  1043.   char   temp;
  1044.  
  1045.   /* byte swap the input field                                      */
  1046.   onion.llen   = inval;
  1047.   temp   = onion.ichar[0];
  1048.   onion.ichar[0]=onion.ichar[3];
  1049.   onion.ichar[3]=temp;
  1050.   temp   = onion.ichar[1];
  1051.   onion.ichar[1]=onion.ichar[2];
  1052.   onion.ichar[2]=temp;
  1053.   return (onion.llen);
  1054. }
  1055.  
  1056.  void decompress(ibuf,obuf,nin,nout)
  1057. /****************************************************************************
  1058. *_TITLE decompress - decompresses image lines stored in compressed format   *
  1059. *_ARGS  TYPE       NAME      I/O        DESCRIPTION                         */
  1060.         char       *ibuf;  /* I         Compressed data buffer              */
  1061.         char       *obuf;  /* O         Decompressed image line             */
  1062.         long int   *nin;   /* I         Number of bytes on input buffer     */
  1063.         long int   *nout;  /* I         Number of bytes in output buffer    */
  1064.  
  1065.   {
  1066.  /* The external root pointer to tree */
  1067.     extern NODE *tree;
  1068.  
  1069.  /* Declare functions called from this routine */
  1070.     void dcmprs();
  1071.  
  1072. /*************************************************************************
  1073.   This routine is fairly simple as it's only function is to call the
  1074.   routine dcmprs.
  1075. **************************************************************************/
  1076.  
  1077.     dcmprs(ibuf,obuf,nin,nout,tree);
  1078.  
  1079.     return;
  1080.   }
  1081.  
  1082. void decmpinit(hist)
  1083. /***************************************************************************
  1084. *_TITLE decmpinit - initializes the Huffman tree                           *
  1085. *_ARGS  TYPE       NAME      I/O        DESCRIPTION                        */
  1086.         long int   *hist;  /* I         First-difference histogram.        */
  1087.  
  1088. {
  1089.   extern NODE *tree;          /* Huffman tree root pointer */
  1090.  
  1091.   /* Specify the calling function to initialize the tree */
  1092.   NODE *huff_tree();
  1093.  
  1094. /****************************************************************************
  1095.   Simply call the huff_tree routine and return.
  1096. *****************************************************************************/
  1097.  
  1098.   tree = huff_tree(hist);
  1099.  
  1100.   return;
  1101.  }
  1102.  
  1103. NODE *huff_tree(hist)
  1104. /****************************************************************************
  1105. *_TITLE huff_tree - constructs the Huffman tree; returns pointer to root    *
  1106. *_ARGS  TYPE          NAME        I/O   DESCRIPTION                         */
  1107.         long int     *hist;     /* I    First difference histogram          */
  1108.  
  1109.   {
  1110.   /*  Local variables used */
  1111.     long int freq_list[512];      /* Histogram frequency list */
  1112.     NODE **node_list;             /* DN pointer array list */
  1113.  
  1114.     register long int *fp;        /* Frequency list pointer */
  1115.     register NODE **np;           /* Node list pointer */
  1116.  
  1117.     register long int num_freq;   /* Number non-zero frequencies in
  1118. histogram */
  1119.     long int sum;                 /* Sum of all frequencies */
  1120.  
  1121.     register short int num_nodes; /* Counter for DN initialization */
  1122.     register short int cnt;       /* Miscellaneous counter */
  1123.  
  1124.     short int znull = -1;         /* Null node value */
  1125.  
  1126.     register NODE *temp;          /* Temporary node pointer */
  1127.  
  1128.   /* Functions called */
  1129.     void sort_freq();
  1130.     NODE *new_node();
  1131.     char *malloc();
  1132.  
  1133. /***************************************************************************
  1134.   Allocate the array of nodes from memory and initialize these with numbers
  1135.   corresponding with the frequency list.  There are only 511 possible
  1136.   permutations of first difference histograms.  There are 512 allocated
  1137.   here to adhere to the FORTRAN version.
  1138. ****************************************************************************/
  1139.  
  1140.    fp = freq_list;
  1141.    node_list = (NODE **) malloc(sizeof(temp)*512);
  1142.    if (node_list == NULL)
  1143.     {
  1144.       fprintf(stderr,"\nOut of memory in huff_tree!\n");
  1145.       exit(1);
  1146.     }
  1147.    np = node_list;
  1148.  
  1149.    for (num_nodes=1, cnt=512 ; cnt-- ; num_nodes++)
  1150.      {
  1151. /**************************************************************************
  1152.     The following code has been added to standardize the VAX byte order
  1153.     for the "long int" type.  This code is intended to make the routine
  1154.     as machine independant as possible.
  1155. ***************************************************************************/
  1156.         unsigned char *cp = (unsigned char *) hist++;
  1157.         unsigned long int j;
  1158.         short int i;
  1159.         for (i=4 ; --i >= 0 ; j = (j << 8) | *(cp+i));
  1160.  
  1161. /* Now make the assignment */
  1162.         *fp++ = j;
  1163.         temp = new_node(num_nodes);
  1164.         *np++ = temp;
  1165.      }
  1166.  
  1167.      (*--fp) = 0;         /* Ensure the last element is zeroed out.  */
  1168.  
  1169. /***************************************************************************
  1170.   Now, sort the frequency list and eliminate all frequencies of zero.
  1171. ****************************************************************************/
  1172.  
  1173.   num_freq = 512;
  1174.   sort_freq(freq_list,node_list,num_freq);
  1175.  
  1176.   fp = freq_list;
  1177.   np = node_list;
  1178.  
  1179.   for (num_freq=512 ; (*fp) == 0 && (num_freq) ; fp++, np++, num_freq--);
  1180.  
  1181.  
  1182. /***************************************************************************
  1183.   Now create the tree.  Note that if there is only one difference value,
  1184.   it is returned as the root.  On each interation, a new node is created
  1185.   and the least frequently occurring difference is assigned to the right
  1186.   pointer and the next least frequency to the left pointer.  The node
  1187.   assigned to the left pointer now becomes the combination of the two
  1188.   nodes and it's frequency is the sum of the two combining nodes.
  1189. ****************************************************************************/
  1190.  
  1191.   for (temp=(*np) ; (num_freq--) > 1 ; )
  1192.     {
  1193.         temp = new_node(znull);
  1194.         temp->right = (*np++);
  1195.         temp->left = (*np);
  1196.         *np = temp;
  1197.         *(fp+1) = *(fp+1) + *fp;
  1198.         *fp++ = 0;
  1199.         sort_freq(fp,np,num_freq);
  1200.     }
  1201.  
  1202.   return temp;
  1203.  }
  1204.  
  1205. NODE *new_node(value)
  1206. /****************************************************************************
  1207. *_TITLE new_node - allocates a NODE structure and returns a pointer to it   *
  1208. *_ARGS  TYPE        NAME        I/O     DESCRIPTION                         */
  1209.         short int   value;    /* I      Value to assign to DN field         */
  1210.  
  1211.   {
  1212.     NODE *temp;         /* Pointer to the memory block */
  1213.  
  1214.   char *malloc();       /* Memory allocation function */
  1215.  
  1216. /***************************************************************************
  1217.   Allocate the memory and intialize the fields.
  1218. ****************************************************************************/
  1219.  
  1220.   temp = (NODE *) malloc(sizeof(NODE));
  1221.  
  1222.   if (temp != NULL)
  1223.     {
  1224.       temp->right = NULL;
  1225.       temp->dn = value;
  1226.       temp->left = NULL;
  1227.     }
  1228.   else
  1229.     {
  1230.        fprintf(stderr,"\nOut of memory in new_node!\n");
  1231.        exit(1);
  1232.     }
  1233.  
  1234.    return temp;
  1235.   }
  1236.  
  1237.  void sort_freq(freq_list,node_list,num_freq)
  1238. /****************************************************************************
  1239. *_TITLE sort_freq - sorts frequency and node lists in increasing freq. order*
  1240. *_ARGS  TYPE       NAME            I/O  DESCRIPTION                         */
  1241.         long int   *freq_list;   /* I   Pointer to frequency list           */
  1242.         NODE       **node_list;  /* I   Pointer to array of node pointers   */
  1243.         long int   num_freq;     /* I   Number of values in freq list       */
  1244.  
  1245.   {
  1246.     /* Local Variables */
  1247.     register long int *i;       /* primary pointer into freq_list */
  1248.     register long int *j;       /* secondary pointer into freq_list */
  1249.  
  1250.     register NODE **k;          /* primary pointer to node_list */
  1251.     register NODE **l;          /* secondary pointer into node_list */
  1252.  
  1253.     long int temp1;             /* temporary storage for freq_list */
  1254.     NODE *temp2;                /* temporary storage for node_list */
  1255.  
  1256.     register long int cnt;      /* count of list elements */
  1257.  
  1258.  
  1259. /************************************************************************
  1260.   Save the current element - starting with the second - in temporary
  1261.   storage.  Compare with all elements in first part of list moving
  1262.   each up one element until the element is larger.  Insert current
  1263.   element at this point in list.
  1264. *************************************************************************/
  1265.  
  1266.    if (num_freq <= 0) return;      /* If no elements or invalid, return */
  1267.  
  1268.    for (i=freq_list, k=node_list, cnt=num_freq ; --cnt ; *j=temp1, *l=temp2)
  1269.      {
  1270.         temp1 = *(++i);
  1271.         temp2 = *(++k);
  1272.  
  1273.         for (j = i, l = k ;  *(j-1) > temp1 ; )
  1274.           {
  1275.             *j = *(j-1);
  1276.             *l = *(l-1);
  1277.             j--;
  1278.             l--;
  1279.             if ( j <= freq_list) break;
  1280.           }
  1281.  
  1282.      }
  1283.   return;
  1284.   }
  1285.  
  1286.  void dcmprs(ibuf,obuf,nin,nout,root)
  1287. /****************************************************************************
  1288. *_TITLE dcmprs - decompresses Huffman coded compressed image lines          *
  1289. *_ARGS  TYPE       NAME       I/O       DESCRIPTION                         */
  1290.         char       *ibuf;   /* I        Compressed data buffer              */
  1291.         char       *obuf;   /* O        Decompressed image line             */
  1292.         long int   *nin;    /* I        Number of bytes on input buffer     */
  1293.         long int   *nout;   /* I        Number of bytes in output buffer    */
  1294.         NODE       *root;   /* I        Huffman coded tree                  */
  1295.  
  1296.   {
  1297.     /* Local Variables */
  1298.     register NODE *ptr = root;        /* pointer to position in tree */
  1299.     register unsigned char test;      /* test byte for bit set */
  1300.     register unsigned char idn;       /* input compressed byte */
  1301.  
  1302.     register char odn;                /* last dn value decompressed */
  1303.  
  1304.     char *ilim = ibuf + *nin;         /* end of compressed bytes */
  1305.     char *olim = obuf + *nout;        /* end of output buffer */
  1306.  
  1307. /**************************************************************************
  1308.   Check for valid input values for nin, nout and make initial assignments.
  1309. ***************************************************************************/
  1310.  
  1311.     if (ilim > ibuf && olim > obuf)
  1312.        odn = *obuf++ = *ibuf++;
  1313.     else
  1314.        {
  1315.            fprintf(stderr,"\nInvalid byte count in dcmprs!\n");
  1316.            exit(1);
  1317.        }
  1318.  
  1319. /**************************************************************************
  1320.   Decompress the input buffer.  Assign the first byte to the working
  1321.   variable, idn.  An arithmatic and (&) is performed using the variable
  1322.   'test' that is bit shifted to the right.  If the result is 0, then
  1323.   go to right else go to left.
  1324. ***************************************************************************/
  1325.  
  1326.     for (idn=(*ibuf) ; ibuf < ilim  ; idn =(*++ibuf))
  1327.      {
  1328.         for (test=0x80 ; test ; test >>= 1)
  1329.            {
  1330.             ptr = (test & idn) ? ptr->left : ptr->right;
  1331.  
  1332.             if (ptr->dn != -1)
  1333.               {
  1334.                 if (obuf >= olim) return;
  1335.                 odn -= ptr->dn + 256;
  1336.                 *obuf++ = odn;
  1337.                 ptr = root;
  1338.               }
  1339.           }
  1340.      }
  1341.    return;
  1342.   }
  1343.  
  1344.  
  1345. void free_tree(nfreed)
  1346. /****************************************************************************
  1347. *_TITLE free_tree - free memory of all allocated nodes                      *
  1348. *_ARGS  TYPE       NAME       I/O        DESCRIPTION                        */
  1349.         long int   *nfreed;  /* O        Return of total count of nodes     *
  1350. *                                        freed.                             */
  1351.  
  1352. /*
  1353. *_DESCR This routine is supplied to the programmer to free up all the       *
  1354. *       allocated memory required to build the huffman tree.  The count     *
  1355. *       of the nodes freed is returned in the parameter 'nfreed'.  The      *
  1356. *       purpose of the routine is so if the user wishes to decompress more  *
  1357. *       than one file per run, the program will not keep allocating new     *
  1358. *       memory without first deallocating all previous nodes associated     *
  1359. *       with the previous file decompression.                               *
  1360.  
  1361. *_HIST  16-AUG-89 Kris Becker   USGS, Flagstaff Original Version            *
  1362. *_END                                                                       *
  1363. ****************************************************************************/
  1364.  
  1365. {
  1366.     long int total_free = 0;
  1367.  
  1368.     extern NODE *tree;      /* Huffman tree root pointer */
  1369.  
  1370. /* Specify the function to free the tree */
  1371.     long int free_node();
  1372. /****************************************************************************
  1373.   Simply call the free_node routine and return the result.
  1374. *****************************************************************************/
  1375.  
  1376.     *nfreed = free_node(tree,total_free);
  1377.  
  1378.     return;
  1379. }
  1380.  
  1381. long int free_node(pnode,total_free)
  1382. /***************************************************************************
  1383. *_TITLE free_node - deallocates an allocated NODE pointer
  1384. *_ARGS  TYPE     NAME          I/O   DESCRIPTION                           */
  1385.         NODE     *pnode;       /* I  Pointer to node to free               */
  1386.         long int total_free;   /* I  Total number of freed nodes           */
  1387.  
  1388. /*
  1389. *_DESCR  free_node will check both right and left pointers of a node       *
  1390. *        and then free the current node using the free() C utility.        *
  1391. *        Note that all nodes attached to the node via right or left        *
  1392. *        pointers area also freed, so be sure that this is the desired     *
  1393. *        result when calling this routine.                                 *
  1394.  
  1395. *        This routine is supplied to allow successive calls to the         *
  1396. *        decmpinit routine.  It will free up the memory allocated          *
  1397. *        by previous calls to the decmpinit routine.  The call to free     *
  1398. *        a previous huffman tree is:  total = free_node(tree,(long) 0);    *
  1399. *        This call must be done by the programmer application routine      *
  1400. *        and is not done by any of these routines.                         *
  1401. *_HIST   16-AUG-89  Kris Becker U.S.G.S  Flagstaff Original Version        */
  1402. {
  1403.     if (pnode == (NODE *) NULL) return(total_free);
  1404.     
  1405.     if (pnode->right != (NODE *) NULL)
  1406.         total_free = free_node(pnode->right,total_free);
  1407.     if (pnode->left != (NODE *) NULL)
  1408.         total_free = free_node(pnode->left,total_free);
  1409.  
  1410.     free((char *) pnode);
  1411.     return(total_free + 1);
  1412. }
  1413.  
  1414. @//E*O*F pdsuncomp.c//
  1415. chmod u=rw,g=r,o=r pdsuncomp.c
  1416.  
  1417. echo x - xvpds.c
  1418. sed 's/^@//' > "xvpds.c" <<'@//E*O*F xvpds.c//'
  1419. /*
  1420.  * xvpds.c - load routine for astronomical PDS/VICAR format pictures
  1421.  *
  1422.  * Anthony A. Datri
  1423.  * Convex Computer Corp
  1424.  * 3000 Waterview Parkway
  1425.  * Ricardson, TX 75080
  1426.  * datri@convex.com
  1427.  *
  1428.  * 9-2-91    began integration.     Much of this code is lifted from vicar.c,
  1429.  *         which I wrote for xloadimage.  This is a little simpler, though.
  1430.  * code to identify and read in PDS/VICAR images, as found on the CD-ROMS from
  1431.  * NASA, and on ames.arc.nasa.gov.
  1432.  *
  1433.  * 10-17-91  pdsuncomp is called with system(), which typically feeds the
  1434.  *         commandline to sh.  Make sure that your .profile adds wherever
  1435.  *         you have pdsuncomp to the PATH, like
  1436.  *
  1437.  *        PATH=$PATH:/usr/local/bin
  1438.  *
  1439.  *
  1440.  * Sources of these CD's:
  1441.  *
  1442.  *  National Space Science Data Center
  1443.  *  Goddard Space Flight Center
  1444.  *  Code 933.4
  1445.  *  Greenbelt, Maryland  
  1446.  *  (301) 286-6695
  1447.  *   or call
  1448.  *  (301) 286-9000 (300,1200,2400 bps)
  1449.  *   or telnet
  1450.  *  nssdca.gsfc.nasa.gov (128.183.10.4) and log in as 'NODIS' (no password).
  1451.  *
  1452.  *  Randy Davis
  1453.  *  LASP
  1454.  *  University of Colorado
  1455.  *  Boulder CO 80309-0392
  1456.  *  (303) 492-6867
  1457.  * These CD's are reasonably priced.  Encourage the continue production
  1458.  * of them by buying a set.
  1459.  * There are three types of files that we deal with here.  I'll call them
  1460.  * PDS-labeled, PDS-labeled Huffman-encoded, and VICAR.  Each consists of data
  1461.  * prefixed with a set of ASCII headers.  PDS-labeled and VICAR files are raw
  1462.  * grayscale data, the dimensions of which can be found from the headers.
  1463.  * PDS-labeled, Huffman-encoded files have the image information adaptively
  1464.  * Huffman-encoded, and the encoding histogram follows the ASCII headers.
  1465.  * To decode these, we use an extended version of "cdcomp.c" from the
  1466.  * NASA Vger CD-ROMS.  For this to work, you need to have pdscomp compiled
  1467.  * and in your path.  pdscomp.c should be included with this distribution.
  1468.  * I've heard that newer discs have FITS images on them.  If they do, support
  1469.  * for them will be added when I get one.  Until then, you can use fitstopgm.
  1470.  *
  1471.  * strstr is used extensively here.  If your machine doesn't have strstr,
  1472.  * you need to do two things:
  1473.  *
  1474.  *   o uncomment the STRSTRF def in the Makefile to get a free version
  1475.  *   o beat up your vendor for not giving it to you
  1476.  *
  1477.  *  SunOS didn't have it until 4.1, for example
  1478.  *
  1479.  *
  1480.  * LoadPDS(fname, numcols)  -  coerces a PDS/VICAR image
  1481.  * WriteVICAR(fp, pic, w, h, r,g,b, numcols, style)
  1482.  */
  1483.  
  1484. /*
  1485.  * Copyright 1989, 1990 by Anthony A. Datri
  1486.  *
  1487.  * Permission to use, copy, and distribute for non-commercial purposes,
  1488.  * is hereby granted without fee, providing that the above copyright
  1489.  * notice appear in all copies and that both the copyright notice and this
  1490.  * permission notice appear in supporting documentation.
  1491.  *
  1492.  * This software is provided "as is" without any express or implied warranty.
  1493.  */
  1494.  
  1495.  
  1496. #include "xv.h"
  1497.  
  1498. #ifndef TRUE
  1499. #define TRUE (1)
  1500. #define FALSE (0)
  1501. #endif
  1502.  
  1503. #define PDSFIXED    (1)
  1504. #define    PDSVARIABLE    (2)
  1505. #define PDSTRASH    (-1)
  1506. #define VICAR        (3)
  1507. #define MAX_SIZE    20480 /*10240*/    /* a guess -- even magellan images aren't
  1508.                     bigger than 2k x 2k */
  1509. #define RTBUFFSIZE    20    /* small buffer for magic */
  1510. #define FNAMESIZE    1024    /* too hard to generalize really getting it */
  1511. #define PDSUNCOMP    "pdsuncomp" /* filter to un-Huffmanize */
  1512. /* This is arbitrary.  Everything I've seen so far fits */
  1513. #define COMMENTSIZE    50
  1514.  
  1515.  
  1516. static char    scanbuff[MAX_SIZE], rtbuff[RTBUFFSIZE], infobuff[COMMENTSIZE],
  1517.         spacecraft[COMMENTSIZE],
  1518.         target[COMMENTSIZE],
  1519.         filtname[COMMENTSIZE],
  1520.         mphase[COMMENTSIZE],
  1521.         iname[COMMENTSIZE],
  1522.         itime[COMMENTSIZE],
  1523.         pdsuncompfname[FNAMESIZE];
  1524. byte *image;
  1525.  
  1526.  
  1527. /* here's an strstr for the libc-impaired */
  1528.  
  1529. #ifdef NOSTRSTR
  1530. /* 
  1531.  * strstr.c --
  1532.  *
  1533.  *    Source code for the "strstr" library routine.
  1534.  *
  1535.  * Copyright 1988 Regents of the University of California
  1536.  * Permission to use, copy, modify, and distribute this
  1537.  * software and its documentation for any purpose and without
  1538.  * fee is hereby granted, provided that the above copyright
  1539.  * notice appear in all copies.  The University of California
  1540.  * makes no representations about the suitability of this
  1541.  * software for any purpose.  It is provided "as is" without
  1542.  * express or implied warranty.
  1543.  */
  1544.  
  1545. #ifndef lint
  1546. static char rcsid[] = "$Header: /sprite/src/lib/c/string/RCS/strstr.c,v
  1547. 1.2 89/03/22 16:07:57 rab Exp $ SPRITE (Berkeley)";
  1548. #endif /* not lint */
  1549.  
  1550. /*
  1551.  *----------------------------------------------------------------------
  1552.  *
  1553.  * strstr --
  1554.  *
  1555.  *    Locate the first instance of a substring in a string.
  1556.  *
  1557.  * Results:
  1558.  *    If string contains substring, the return value is the
  1559.  *    location of the first matching instance of substring
  1560.  *    in string.  If string doesn't contain substring, the
  1561.  *    return value is 0.  Matching is done on an exact
  1562.  *    character-for-character basis with no wildcards or special
  1563.  *    characters.
  1564.  *
  1565.  * Side effects:
  1566.  *    None.
  1567.  *
  1568.  *----------------------------------------------------------------------
  1569.  */
  1570.  
  1571. char *
  1572. strstr(string, substring)
  1573.     char *string;    /* String to search. */
  1574.     char *substring;        /* Substring to try to find in string. */
  1575. {
  1576.     register char *a, *b;
  1577.  
  1578.     /* First scan quickly through the two strings looking for a
  1579.      * single-character match.  When it's found, then compare the
  1580.      * rest of the substring.
  1581.      */
  1582.  
  1583.     b = substring;
  1584.     if (*b == 0) {
  1585.     return string;
  1586.     }
  1587.     for ( ; *string != 0; string += 1) {
  1588.     if (*string != *b) {
  1589.         continue;
  1590.     }
  1591.     a = string;
  1592.     while (1) {
  1593.         if (*b == 0) {
  1594.         return string;
  1595.         }
  1596.         if (*a++ != *b++) {
  1597.         break;
  1598.         }
  1599.     }
  1600.     b = substring;
  1601.     }
  1602.     return (char *) 0;
  1603. }
  1604. #endif /* NOSTRSTR */
  1605.  
  1606. /* get a NULL-, CR-, or CRLF-terminated record from a PDS file */
  1607. /* The method of termination is unpredictable.  A pox on VMS   */
  1608.  
  1609. int getpdsrec(f,buff)
  1610. FILE *f;
  1611. char *buff; {
  1612.  
  1613.     static char *bp;
  1614.     static int count;
  1615.  
  1616.     count=0;
  1617.     bp=buff;
  1618.     for (;TRUE;) {
  1619.     (*bp)=fgetc(f);
  1620.     switch (*bp) {
  1621.         case '\r':
  1622.         *bp='\0';
  1623.         switch ((*(bp+1))=fgetc(f)) {
  1624.             case EOF:
  1625.             case '\n':
  1626.             break;
  1627.             default:
  1628.             ungetc(*(bp+1),f);
  1629.             }
  1630.         return(count);
  1631.         case EOF:
  1632.         *bp='\0';
  1633.         return(count);            
  1634.         case '\0':
  1635.         return(count);
  1636.         default:
  1637.         count++;
  1638.         bp++;
  1639.       }
  1640.     }
  1641. }
  1642.  
  1643. /* A VICAR image seems to begin with a one-line header describing all sorts
  1644.  * of things, almost all of which don't mean much to Joe User, who just
  1645.  * wants to see what Venus looks like.  The first thing in this label is a
  1646.  * string defining the size of the label, like "LBLSIZE=2048".  Then there's
  1647.  * other crud of variable usefulness.  Important to us are the NL and NS
  1648.  * fields, which seem to tell us the number of columns and rows, respectively.
  1649.  * Among these other fields seem to be the local map coordinates of the region.
  1650.  * These files are easy -- you can even convert one to usefulness by grabbing
  1651.  * the dimensions and lblsize and feeding to rawtopgm.  For example, if
  1652. lblsize,
  1653.  * nl, and ns are 2048, 1536, and 2048, respectively, use "rawtopgm -headerskip
  1654.  * 2048 2048 1536 <foo.img >foo.pgm.  All of the samples I've seen are 8 bits
  1655.  * deep, so we assume that.  Yeah, yeah, that's nasty and evil, and I'm
  1656.  * terribly ashamed of it, but I'm not going to bother with bit fiddling
  1657.  * until I see an image that requires it
  1658.  *
  1659.  * These images are typically fairly big, so it makes sense to verify the
  1660.  * format before we try to read it all in.
  1661.  *
  1662.  * PDS images are prefixed like this:
  1663.  *
  1664.  *  od -a c2061139.imq | head -a
  1665.  *  0000000    - nul   N   J   P   L   1   I   0   0   P   D   S   1   0   0
  1666.  *
  1667.  * so we'll read off the first two chars, which seem to be a length field
  1668.  * of some kind, then look for NJPL..  But NOOOOOO, images on the Sampler
  1669.  * disc just HAVE to leave off the first two bytes.  Bloody HELL!  This
  1670.  * is the distinction between the fixed and variable-record files.
  1671.  */
  1672.             
  1673.  
  1674.  
  1675.  
  1676.  
  1677. /*******************************************/
  1678. int LoadPDS(fname,nc)
  1679.      char *fname;
  1680.      int   nc;    {
  1681.  
  1682. int tempnum;
  1683. FILE    *zf;
  1684. static int isfixed,teco,i,j,itype,lastwasinote,
  1685.     recsize,hrecsize,irecsize,isimage,labelrecs,labelsofar,
  1686.     x,y,lpsize,lssize,samplesize,returnp,labelsize,yy;
  1687. char    *tmp;
  1688.  
  1689. isfixed=TRUE;
  1690. returnp=isimage=FALSE;
  1691. itype=PDSTRASH;
  1692.  
  1693. teco=i=j=recsize=hrecsize=irecsize=labelrecs=x=y=lpsize=lssize=
  1694.         samplesize=labelsize=labelsofar=0;
  1695. (*pdsuncompfname)=(*iname)=(*target)=(*filtname)=(*itime)=(*spacecraft)=(*scanb
  1696. uff)=
  1697.         (*mphase)=(*rtbuff)='\0';
  1698.  
  1699. /* there may be some wisdom in statically mallocing space for an 800x800
  1700.    image, since that's what the Voyager cd's have, or even a 2kx2k, since
  1701.    some of the Magellan images from ames are that size */
  1702.  
  1703.  
  1704. zf=fopen(fname,"r");
  1705. if (!zf) {
  1706.     SetISTR(ISTR_INFO,"LoadPDS: can't open %s\n",fname);
  1707.     return(1);
  1708. }
  1709.  
  1710. /* read the magic.  If it's got two bytes of crud in front of it, it's
  1711.    a damned "variable-length-record" file, and we have to jump through
  1712.    bloody VAX hoops, and feed it through pdsuncomp to get useful bits */
  1713.  
  1714. if ((teco=fread(rtbuff,13,1,zf)) != 1) {
  1715.    SetISTR(ISTR_INFO,"LoadPDS: couldn't read magic: %d,%s",teco,fname);
  1716.    Warning();
  1717.    fclose(zf);
  1718.    return(1);
  1719. }
  1720.  
  1721. rtbuff[13]='\0';    /* this makes sscanf so much happier */
  1722.  
  1723. if ((strncmp(rtbuff, "NJPL1I00PDS",11) == 0) ||
  1724.     ((isfixed=strncmp(rtbuff+2,"NJPL1I00PDS",11)) == 0)) {
  1725.  
  1726.     /* we only handle 8 b/p right now */
  1727.     SetISTR(ISTR_FORMAT, isfixed ? "PDS/VICAR, 8 bits per pixel." :
  1728.                     "Huffman-encoded PDS, 8 bits per pixel.");
  1729.  
  1730.     if (!(isfixed)) {
  1731.     teco = ((*rtbuff) + ((*(rtbuff+1)) << 8));
  1732.     fread(rtbuff,(teco % 2 ? teco + 1 : teco ) - 11,1,zf);
  1733.     }
  1734.  
  1735.  
  1736.     /* we know that we've got a PDS file of some sort.    We have to
  1737.        search through the labels looking for things because usage doesn't seem
  1738.        to be consistent, or even predictable.  When I added this format to
  1739.        xloadimage, I had the code spew out various peices of information, like
  1740.        the name of the target, filter used, etc.  Xv, however, doesn't really
  1741.        provide precedent for this kind of thing, and I can't really stick it
  1742.        into the info box without overhauling it.  Maybe later I'll add a
  1743.        -verbose switch which this module will interpret as license to scribble
  1744.        on stdout or stderr */
  1745.  
  1746.     for (;;) {
  1747.     if (isfixed) {
  1748.         if (getpdsrec(zf,scanbuff) == 0) {
  1749.         SetISTR(ISTR_INFO,
  1750.             "corrupt or incomplete PDS labels (low fread)");
  1751.         Warning();
  1752.         break;
  1753.         }
  1754.     } else {
  1755.         /* AAAARGGGGH!  We've got a bloody variable-length file where
  1756.          * the headers are preceded by a byte count, as a VAX 16-bit
  1757.          * integer of all things.  VMS:  Just Say NFW.
  1758.          * "A compressed image file is composed of variable-length records
  1759.          * defined according to the ISO standard.  Each variable length
  1760.          * record starts with a record length indicator, stored as a 16-bit
  1761.          * integer, followed by the number of bytes indicated in the record
  1762.          * length indicator. If the length indicator is odd, then a pad byte
  1763.          * is appended to the end of the record so that all records contain
  1764.          * an even number of bytes."*/
  1765.                                                                         
  1766.  
  1767.         i=getc(zf);
  1768.         j=getc(zf);
  1769.         if (j == EOF) {
  1770.         SetISTR(ISTR_INFO,"LoadPDS: j is EOF\n");
  1771.         fclose(zf);
  1772.         return(1);
  1773.         }
  1774.         teco = i + (j << 8);
  1775.         if (teco % 2) {
  1776.         teco++;
  1777.         }
  1778.         if (fread(scanbuff,teco,1,zf) != 1) {
  1779.         SetISTR(ISTR_INFO,"LoadPDS: bad fread reading labels\n");
  1780.         fclose(zf);
  1781.         return(1);
  1782.         }
  1783.         scanbuff[teco]='\0';
  1784.     }
  1785.  
  1786.     /* otay, we've managed to wrestle a header of some sort from the
  1787.        file -- now we grep through until we hit the END, at which point
  1788.        we break out of the loop and see what we've got.  In the future,
  1789.        we'll check for informational headers and write them out if the
  1790.        fool user wants them.  There seems to be disagreement about what
  1791.        the headers are called, since we might find, for example, either
  1792.        TARGET_BODY or TARGET_NAME.    Bloody 'ell. */
  1793.  
  1794.     if (strcmp(scanbuff,"END") == 0) {
  1795.         break;
  1796.     } else if (sscanf(scanbuff,"RECORD_TYPE = %s",rtbuff) == 1) {
  1797.         if (strncmp(rtbuff,"VARIABLE_LENGTH",15) == 0) {
  1798.         itype=PDSVARIABLE;
  1799.         } else if (strncmp(rtbuff,"FIXED_LENGTH",12) == 0) {
  1800.         itype=PDSFIXED;
  1801.         } else {
  1802.         rtbuff[RTBUFFSIZE-1]='\0'; /* juuuust in case */
  1803.         SetISTR(ISTR_INFO,
  1804.             "LoadPDS: unsupported record type \"%s\"\n",rtbuff);
  1805.         fclose(zf);
  1806.         return(1);
  1807.         }
  1808.     } else if (sscanf(scanbuff,"RECORD_BYTES = %d",&recsize) == 1) {
  1809.         /* these default to RECORD_BYTES unless explicitly set */
  1810.         if (hrecsize == 0)
  1811.         hrecsize=recsize;
  1812.         if (irecsize == 0)
  1813.         irecsize=recsize;
  1814.         continue;
  1815.        } else if (sscanf(scanbuff,"FILE_TYPE = %s", rtbuff) != NULL) {
  1816.         if (strncmp(rtbuff,"IMAGE",5) == 0) {
  1817.         isimage=TRUE;
  1818.         continue;
  1819.         } else {
  1820.         isimage=FALSE;
  1821.         break;
  1822.         }
  1823.     } else if ((sscanf(scanbuff," HEADER_RECORDS = %d",&labelrecs) == 1) ||
  1824.            (sscanf(scanbuff," LABEL_RECORDS = %d", &labelrecs) == 1)) {
  1825.         continue;
  1826.     } else if (sscanf(scanbuff," IMAGE_LINES = %d",&y) == 1) {
  1827.          isimage=TRUE; continue;
  1828.     } else if (sscanf(scanbuff," LINE_SAMPLES = %d",&x) == 1) {
  1829.          continue;
  1830.     } else if (sscanf(scanbuff," LINES = %d",&y) == 1) {
  1831.          isimage=TRUE; continue;
  1832.     } else if (sscanf(scanbuff," HEADER_RECORD_BYTES = %d",&hrecsize)==1) {
  1833.          continue;
  1834.     } else if (sscanf(scanbuff," IMAGE_RECORD_BYTES = %d",&irecsize)==1) {
  1835.          continue;
  1836.     } else if (sscanf(scanbuff," LINE_PREFIX_BYTES = %d",&lpsize)==1) {
  1837.          continue;
  1838.     } else if (sscanf(scanbuff," LINE_SUFFIX_BYTES = %d",&lssize)==1) {
  1839.          continue;
  1840.     } else if (sscanf(scanbuff," SAMPLE_BITS = %d", &samplesize) == 1) {
  1841.          continue;
  1842.     } else if (sscanf(scanbuff," SPACECRAFT_NAME = %s", spacecraft) == 1) {
  1843.          continue;
  1844. /*    } else if (sscanf(scanbuff," MISSION_PHASE_NAME = %s", mphase) == 1) {
  1845.          continue;
  1846.     } else if (sscanf(scanbuff," MISSION_PHASE = %s", mphase) == 1) {
  1847.          continue;*/
  1848.     } else if (sscanf(scanbuff," TARGET_NAME = %s", target) == 1) {
  1849.          continue;
  1850.     } else if (sscanf(scanbuff," TARGET_BODY = %s", target) == 1) {
  1851.          continue;
  1852. /*    } else if (sscanf(scanbuff," INSTRUMENT_NAME = %s", iname) == 1) {
  1853.          continue;*/
  1854.     } else if (sscanf(scanbuff," SPACECRAFT_EVENT_TIME = %s", itime) == 1) {
  1855.          continue;
  1856.     } else if (sscanf(scanbuff," IMAGE_TIME = %s", itime) == 1) {
  1857.          continue;
  1858.     } else if (sscanf(scanbuff," FILTER_NAME = %s", filtname) == 1) {
  1859.          continue;
  1860.     } else if (sscanf(scanbuff," INSTRUMENT_FILTER_NAME = %s", filtname) == 1) {
  1861.          continue;
  1862.     }
  1863. /* I never did understand any of these
  1864.     } else if (sscanf(scanbuff," GAIN_MODE_ID = %s", gainmode) == 1) {
  1865.          continue;
  1866.     } else if (sscanf(scanbuff," INSTRUMENT_GAIN_STATE = %s", gainmode) == 1) {
  1867.          continue;
  1868.     } else if (sscanf(scanbuff," EDIT_MODE_ID = %s", editmode) == 1) {
  1869.          continue;
  1870.     } else if (sscanf(scanbuff," INSTRUMENT_EDIT_MODE = %s", editmode) == 1) {
  1871.          continue;
  1872.     } else if (sscanf(scanbuff," SCAN_MODE_ID = %s", scanmode) == 1) {
  1873.          continue;
  1874.     } else if (sscanf(scanbuff," INSTRUMENT_SCAN_RATE = %s", scanmode) == 1) {
  1875.          continue;
  1876.     } else if (sscanf(scanbuff," SHUTTER_MODE_ID = %s", shutmode) == 1) {
  1877.          continue;
  1878.     } else if (sscanf(scanbuff," INSTRUMENT_SHUTTER_MODE = %s", shutmode) == 1) {
  1879.          continue; */
  1880.     }
  1881.  
  1882.     if ((isimage == TRUE) && (labelsize=(labelrecs * hrecsize))) {
  1883.     if (samplesize!= 8) {
  1884.         SetISTR(ISTR_INFO,"This image looks to be %d bits deep, but I can
  1885. only handle 8-bit PDS files\n");
  1886.         fclose(zf);
  1887.         return(1);
  1888.     }
  1889.     } else {
  1890.     SetISTR(ISTR_INFO,"This looks a lot like a PDS/VICAR image, but I can't
  1891. see the size of the label\n");
  1892.     fclose(zf);
  1893.     return(1);
  1894.     }
  1895. /* Some day this should be generalized to read <>8-bit files.  If I ever find
  1896.  * one that's interesting, I'll do the work. */
  1897.  
  1898. } else if (sscanf(rtbuff,"LBLSIZE = %d%n",&labelsize,&labelsofar) == 1) {
  1899.     /* we've got a VICAR file.  Let's find out how big the puppy is */
  1900.     itype=VICAR;
  1901.     if (fread(scanbuff,labelsize-labelsofar,1,zf) == 1) {
  1902.         if ((tmp=strstr(scanbuff,"NL=")) == NULL) {
  1903.         SetISTR(ISTR_INFO,"LoadPDS: bad NL in VICAR\n");
  1904.         returnp=TRUE;
  1905.         }
  1906.         if (sscanf(tmp,"NL = %d",&y) != 1) {
  1907.         SetISTR(ISTR_INFO,"LoadPDS: bad scan NL in VICAR\n");
  1908.         returnp=TRUE;
  1909.         }
  1910.         if ((tmp=strstr(scanbuff, "NS=")) == NULL) {
  1911.         SetISTR(ISTR_INFO,"LoadPDS: bad NS in VICAR\n");
  1912.         returnp=TRUE;
  1913.         }
  1914.         if (sscanf(tmp, "NS = %d",&x) != 1) {
  1915.         SetISTR(ISTR_INFO,"LoadPDS: bad scan NS in VICAR\n");
  1916.         returnp=TRUE;
  1917.         }
  1918.     }
  1919. } else {
  1920.     SetISTR(ISTR_INFO,"LoadPDS: I guess this isn't one of mine after all\n");
  1921.     returnp=TRUE;
  1922. }
  1923.  
  1924. if (returnp) {
  1925.     fclose(zf);
  1926.     return(1);
  1927. }
  1928.  
  1929. /* PDS files tend to have lots of information like this in them.  The
  1930.  * following are a few of the more interesting headers.  We'd do more, but
  1931.  * there's only so much space in the info box */
  1932.  
  1933. *infobuff='\0';
  1934. if (*spacecraft) {
  1935.     strcat(infobuff,spacecraft);
  1936. }
  1937. if (*target) {
  1938.     strcat(infobuff,", ");
  1939.     strcat(infobuff,target);
  1940. }
  1941. if (*filtname) {
  1942.     strcat(infobuff,", ");
  1943.     strcat(infobuff,filtname);
  1944. }
  1945. if (*itime) {
  1946.     strcat(infobuff,", ");
  1947.     strcat(infobuff,itime);
  1948. }
  1949. SetISTR(ISTR_WARNING,infobuff);
  1950.  
  1951. strcpy(pdsuncompfname,fname);
  1952. switch (itype) {
  1953.     case VICAR:
  1954.     SetISTR(ISTR_FORMAT, "VICAR, 8 bits per pixel.");
  1955.     rewind(zf);
  1956.     break;
  1957.     case PDSFIXED:
  1958.     SetISTR(ISTR_FORMAT, "PDS, 8 bits per pixel.");
  1959.     rewind(zf);
  1960.     break;
  1961.     case PDSVARIABLE:
  1962.     SetISTR(ISTR_FORMAT, "PDS, 8 bits per pixel, Huffman-encoded.");
  1963.     fclose(zf);
  1964. /*    strcat(fname,".out");*/
  1965.     strcpy(pdsuncompfname,"/tmp/xvhuffXXXXXX");
  1966.     mktemp(pdsuncompfname);
  1967.     sprintf(scanbuff,"%s %s - 4 >%s",PDSUNCOMP,fname,pdsuncompfname);
  1968.     SetISTR(ISTR_INFO,"De-Huffmanizing '%s'...",fname);
  1969.     /* pdsuncomp filters to a raw file */
  1970.     if (tempnum=system(scanbuff)) {
  1971.         SetISTR(ISTR_INFO,"Unable to de-Huffmanize '%s'.",fname);
  1972. /*fprintf(stderr,"system returned %d\n",tempnum);fflush(stderr);*/
  1973.         Warning();
  1974.         return(1);
  1975.     }
  1976. fprintf(stderr,"system returned %d\n",tempnum);fflush(stderr);
  1977.     zf=fopen(pdsuncompfname,"r");
  1978.     if (!zf) {
  1979.         SetISTR(ISTR_INFO,"LoadPDS: can't open uncompressed file %s\n",
  1980.                       pdsuncompfname);
  1981.         Warning();
  1982.         return(1);
  1983.     }
  1984.     }
  1985.  
  1986. /* skip headers */
  1987.  
  1988. if (itype != PDSVARIABLE) {
  1989.     fread(scanbuff,labelsize,1,zf);
  1990. }
  1991.  
  1992. image=(byte *)malloc(x*y);
  1993. if (image == NULL) {
  1994.     SetISTR(ISTR_INFO,"LoadPDS: couldn't malloc %d",x*y);
  1995.     Warning();
  1996.     fclose(zf);
  1997.     if (itype==PDSVARIABLE)
  1998.     unlink(pdsuncompfname);
  1999.     exit(1);
  2000. }
  2001.  
  2002. if ((lssize || lpsize) & (itype == PDSFIXED)) {
  2003.     /* ARrrrgh.  Some of these images have crud intermixed with the image, */
  2004.     /* preventing us from freading in one fell swoop (whatever a fell
  2005. swoop is */
  2006.     for (yy=0;yy<y;yy++) {
  2007.     if (lpsize && ((teco=(fread(scanbuff,lpsize,1,zf))) != 1)) {
  2008.         SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading prefix");
  2009.         Warning();
  2010.         fclose(zf);
  2011.         return(1);
  2012.     }
  2013.     if ((teco=(fread(image+(yy*x),x,1,zf))) != 1) {
  2014.         SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading line %d",yy);
  2015.         Warning();
  2016.         fclose(zf);
  2017.         return(1);
  2018.     }
  2019.     if (lssize && ((teco=(fread(scanbuff,lssize,1,zf))) != 1)) {
  2020.         SetISTR(ISTR_INFO, "LoadPDS: unexpected EOF reading suffix");
  2021.         Warning();
  2022.         fclose(zf);
  2023.         return(1);
  2024.     }
  2025.     }
  2026. } else if ((yy=fread(image,x*y,1,zf)) != 1) {
  2027.     SetISTR(ISTR_INFO,"LoadPDS: error reading image data");
  2028.     Warning();
  2029.     fclose(zf);
  2030.     if (itype==PDSVARIABLE)
  2031.             unlink(pdsuncompfname);
  2032.     return(1);
  2033.  
  2034. }
  2035. /*SetISTR(ISTR_INFO,infobuff);*/
  2036. fclose(zf);
  2037. if (itype==PDSVARIABLE)
  2038.     unlink(pdsuncompfname);
  2039.  
  2040. /* fix up xv globals */
  2041.  
  2042. pic = image;
  2043. pWIDE = x;
  2044. pHIGH = y;
  2045.  
  2046. /* these are grayscale, so cobble up a ramped colormap */
  2047.  
  2048. for (yy=0; yy<=255; yy++) {
  2049. /*    *(r+yy)=*(g+yy)=*(b+yy)=yy;*/
  2050.     *(r+yy)=yy;
  2051. }
  2052. /* this is cheating, but saves a few hundred ops */
  2053. memcpy(g,r,256*(sizeof(byte)));
  2054. memcpy(b,r,256*(sizeof(byte)));
  2055.  
  2056. return(0);
  2057. }
  2058. @//E*O*F xvpds.c//
  2059. chmod u=rw,g=r,o=r xvpds.c
  2060.  
  2061. exit 0
  2062. (Message /usr/users/bradley/Mail/inbox:15)
  2063. Return-Path: beser@aplcomm.jhuapl.edu
  2064. Received-Date: Wed, 13 Nov 91 16:52:37 EST
  2065. Received: from aplcomm.jhuapl.edu by central.cis.upenn.edu
  2066.     id AA16950; Wed, 13 Nov 91 16:52:35 -0500
  2067. Posted-Date: Wed, 13 Nov 91 16:52:51 -0500
  2068. Received: by aplcomm.jhuapl.edu (5.61/4.7)
  2069.     id AA25505; Wed, 13 Nov 91 16:52:51 -0500
  2070. Date: Wed, 13 Nov 91 16:52:51 -0500
  2071. From: beser@aplcomm.jhuapl.edu (Nick Beser)
  2072. Message-Id: <9111132152.AA25505@aplcomm.jhuapl.edu>
  2073. To: bradley@central.cis.upenn.edu
  2074.  
  2075. John,
  2076.     I wanted to let you know that I have found a problem with the vicar
  2077. patches that I told you about several weeks ago. I have been attempting to
  2078. read the Viking orbiter images with the modified xv program and have discovered
  2079. a difference in the header information between different PDS formatted images.
  2080. The voyager images have a header that looks like the following:
  2081.  
  2082. uvisiss{beser}45: od -a c1072726.imq | more
  2083. 0000000    - nul   N   J   P   L   1   I   0   0   P   D   S   1   0   0
  2084. 0000020    0   0   0   0   0   0  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp
  2085. 0000040   sp  sp  sp   =  sp   S   F   D   U   _   L   A   B   E   L nul
  2086. 0000060    " nul   /   *  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp   F   I
  2087. 0000100    L   E  sp   F   O   R   M   A   T  sp   A   N   D  sp   L   E
  2088. 0000120    N   G   T   H   2 nul   R   E   C   O   R   D   _   T   Y   P
  2089. 0000140    E  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp
  2090. 0000160   sp  sp  sp  sp  sp  sp  sp   =  sp   V   A   R   I   A   B   L
  2091. 0000200    E   _   L   E   N   G   T   H   & nul   R   E   C   O   R   D
  2092. 0000220    _   B   Y   T   E   S  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp
  2093. 0000240   sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp   =  sp   8   3   6
  2094.  
  2095. The Viking Images have a header that looks like:
  2096.  
  2097. uvisiss{beser}50: od -a f139s01.imq | more
  2098. 0000000    5 nul   C   C   S   D   3   Z   F   0   0   0   0   1   0   0
  2099. 0000020    0   0   0   0   0   1   N   J   P   L   3   I   F   0   P   D
  2100. 0000040    S   2   0   0   0   0   0   0   0   1  sp   =  sp   S   F   D
  2101. 0000060    U   _   L   A   B   E   L nul   % nul   /   *  sp  sp  sp  sp
  2102. 0000100   sp  sp  sp  sp  sp  sp   F   I   L   E  sp   F   O   R   M   A
  2103. 0000120    T  sp   A   N   D  sp   L   E   N   G   T   H  sp   *   / nul
  2104. 0000140    2 nul   R   E   C   O   R   D   _   T   Y   P   E  sp  sp  sp
  2105. 0000160   sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp
  2106. 0000200   sp  sp  sp   =  sp   V   A   R   I   A   B   L   E   _   L   E
  2107. 0000220    N   G   T   H   ' nul   R   E   C   O   R   D   _   B   Y   T
  2108. 0000240    E   S  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp  sp
  2109.  
  2110. The program has two subroutines that parse the header of the PDS files,
  2111. and if it matches the NJPLxx code (in the first 12 bytes of the header,
  2112. it calls it a PDS file. It seems that the program should look at more
  2113. of the header. The two routines are xv.c and xvpds.c. If you are going
  2114. to release a new version of the program I could send you some sample images 
  2115. from Voyager, Magellan, and Viking so you could confirm that they can be
  2116. read. Will you be releasing the code soon? Are you looking for beta testers?
  2117. Please let me know as soon as the code is available.
  2118.  
  2119. Nick Beser
  2120. beser@aplcomm.jhuapl.edu
  2121.  
  2122. (Message /usr/users/bradley/Mail/inbox:13)
  2123. Return-Path: datri@lovecraft.convex.com
  2124. Received-Date: Fri, 22 Nov 91 10:06:05 EST
  2125. Received: from convex.convex.com by central.cis.upenn.edu
  2126.     id AA13501; Fri, 22 Nov 91 10:06:02 -0500
  2127. Posted-Date: Fri, 22 Nov 1991 09:05:46 -0600 (CST)
  2128. Received: from lovecraft.convex.com by convex.convex.com (5.61/1.35)
  2129.     id AA27919; Fri, 22 Nov 91 09:05:50 -0600
  2130. Received: by lovecraft.convex.com (4.1/SMI-4.1)
  2131.     id AA09791; Fri, 22 Nov 91 09:05:48 CST
  2132. Received: from Messages.7.15.N.CUILIB.3.45.SNAP.NOT.LINKED.lovecraft.convex.com.sun4.41
  2133.           via MS.5.6.lovecraft.convex.com.sun4_41;
  2134.           Fri, 22 Nov 1991 09:05:46 -0600 (CST)
  2135. Message-Id: <Ad=Fn_G2e4NhIZT1AT@concave>
  2136. Date: Fri, 22 Nov 1991 09:05:46 -0600 (CST)
  2137. From: "Anthony A. Datri" <datri@concave.convex.com>
  2138. To: bradley@central.cis.upenn.edu
  2139. Subject: new xv module
  2140.  
  2141. I've updated my PDS/VICAR support for xv to handle the format variant
  2142. found on the Viking CD-ROMs.  This includes a new, more general
  2143. decompression program called vdcomp.  There's a tar file of patches on
  2144. convex.com in pub.
  2145.